package cn.edu360.streaming.utils;

import org.jcodings.specific.UTF8Encoding;
import org.joni.*;

import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class GropUtil {
    private static HashMap<String, String> toRegex(String reg, String grokPattern) {
        byte[] str = grokPattern.getBytes();
        Regex regex;
        try {
            regex = new Regex(reg.getBytes("UTF8"), 0,
                    reg.getBytes("UTF8").length, Option.NONE,
                    UTF8Encoding.INSTANCE);
            Matcher matcher = regex.matcher(str);
            int result = matcher.search(0, str.length, Option.DEFAULT);
            HashMap<String, String> json = new HashMap<>();
            if (result != -1) {
                Region region = matcher.getEagerRegion();
                for (Iterator<NameEntry> entry = regex
                        .namedBackrefIterator(); entry.hasNext(); ) {
                    NameEntry e = entry.next();
                    String key = new String(e.name, e.nameP, e.nameEnd - e.nameP);
                    int number = e.getBackRefs()[0];
                    int begin = region.beg[number];
                    int end = region.end[number];
                    if (begin != -1) {
                        String value = new String(str, begin, end - begin, "UTF8");
                        json.put(key, value);
                    }
                }
                return json;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            System.exit(1);
        }
        return null;
    }


    private void loadPatterns(File path, Map<String, String> patterns) {
        if (path.isDirectory()) {
            for (File subPath : path.listFiles())
                loadPatterns(subPath, patterns);
        } else {
            try {
                BufferedReader br = new BufferedReader(new FileReader(path));
                String sCurrentLine;
                while ((sCurrentLine = br.readLine()) != null) {
                    sCurrentLine = sCurrentLine.trim();
                    if (sCurrentLine.length() == 0
                            || sCurrentLine.indexOf("#") == 0) {
                        continue;
                    }
                    patterns.put(sCurrentLine.split("\\s", 2)[0],
                            sCurrentLine.split("\\s", 2)[1]);
                }
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static String convertPattern(String p, Map<String, String> patterns) {
        do {
            String rst = convertPatternOneLevel(p, patterns);
            if (rst.equals(p)) {
                return p;
            }
            p = rst;
        } while (true);
    }

    private static String convertPatternOneLevel(String p, Map<String, String> patterns) {
        String pattern = "\\%\\{[_0-9a-zA-Z]+(:[-_.0-9a-zA-Z]+){0,2}\\}";
        java.util.regex.Matcher m = java.util.regex.Pattern.compile(pattern)
                .matcher(p);
        String newPattern = "";
        int last_end = 0;
        while (m.find()) {
            newPattern += p.substring(last_end, m.start());
            String syntaxANDsemantic = m.group(0).substring(2,
                    m.group(0).length() - 1);
            String syntax, semantic;
            String[] syntaxANDsemanticArray = syntaxANDsemantic.split(":", 3);
            syntax = syntaxANDsemanticArray[0];
            if (syntaxANDsemanticArray.length > 1) {
                semantic = syntaxANDsemanticArray[1];
                newPattern += "(?<" + semantic + ">" + patterns.get(syntax)
                        + ")";
            } else {
                newPattern += patterns.get(syntax);
            }
            last_end = m.end();
        }
        newPattern += p.substring(last_end);
        return newPattern;
    }

    public static HashMap<String, String> stringToJson(String message, String reg, Map<String, String> defaultReg) {
        return toRegex(convertPattern(reg, defaultReg), message.trim());
    }
}